#include "ExploreBot.h"
#include "DIVA_VMStub.h"
#include "xVMRelationStructStub.h"
#include <algorithm>
#include "ExploreBotDialogStub.h"



using namespace std;
#define MAX 500

ExploreBot::ExploreBot(std::string botName,DIVA_VMStub* startVM,int level,int num, vector<string> selectRef)
{
	_botName = botName;
	_byVM = true;
	_startVM = startVM;
	_maxLevel = level;
	_maxNum = num;
	_selectRef = selectRef;
	_exallRef = false;
	_Success = false;
	_ui = NULL;
}

ExploreBot::~ExploreBot()
{

}

ExploreBot::ExploreBot(string botName, string startVMname,int level,int num,vector<string> selectRef,bool save)
{
	_botName = botName;
	_byVM = false;
	_startVM = NULL;
	_maxLevel = level;
/*	_maxLevel = 776655;*/
	_maxNum = num;
/*	_maxNum = 443322;*/
	_startVMname = startVMname;
	_selectRef = selectRef;
	_save = save;
	_Success = false;
	_ui = NULL;
}

bool ExploreBot::doExplor()
{
	if (_byVM)
	{
		if (xVMRelationStructStub::getInstance()->get_subVMs(_startVM).size()==0|| !_startVM->get_visible()){
			_Success = false;
			_message = "Can't Find VM";
		}
		else{
			_Success = true;
			_message = "Working";
			d_expand(_startVM,0, 0);
		}
		
	}
	else if (_startVMname == "[ALL]")
	{
		int _oldvms;
		_Success = true;
		_message = "Working";
		for (int i=0;i<_maxLevel;i++){
		//	_oldvms = xVMRelationStructStub::getInstance()->VMRS_getAllVM().size();
			pickUpAllVMs();
		//	if (_oldvms == xVMRelationStructStub::getInstance()->VMRS_getAllVM().size())
		//		break;
		}
	}
	else
	{
		vector<DIVA_VMStub*> tmp;
		tmp = xVMRelationStructStub::getInstance()->VMRS_searchVMByVarname(_startVMname);
		if (tmp.size() == 0)
		{
			_Success = false;
			_message = "Can't Find VM";
			return false;
		}
		for(int i=0; i<tmp.size();i++)
		{
			_Success = true;
			_message = "Working";
			d_expand(tmp.at(i),0,0);
		}
	}
	return true;

}

void ExploreBot::d_expand(DIVA_VMStub* vm,int nc,int lc){
	int numCount = nc;
	int levelCount = lc;
	deque<DIVA_VMStub *> ret;
	vector<DIVA_VMStub *> chdn ;
	vector<DIVA_VMStub*> exist_vms;
	vector<DIVA_VMStub *>::iterator itr ;
	deque<DIVA_VMStub *>::iterator itr2 ;
	DIVA_VMStub * p;

	chdn = xVMRelationStructStub::getInstance()->get_subVMs(vm);
	ret.push_back(vm);
	
	// since we only click on reference VM 
	for (itr = chdn.begin(); itr != chdn.end(); itr++) {
		p = (*itr);		
		if(p->getVMType() != "reference") 
			continue;
		if (!((checkExplorRef(p->get_vm_name())) || _exallRef))
			continue;
		//if(!checkName(p))   // compare p with the names input in Explore_Dialog
		//	continue;
		if(_maxNum>0 && numCount >= _maxNum) return;

		ReferenceVMStub* refp = ((ReferenceVMStub*)p);

		refp->VMPicked(0,0,0);

		if(xVMRelationStructStub::getInstance()->isPointedNULL(refp)) continue;

		DIVA_VMStub* son = xVMRelationStructStub::getInstance()->get_pointedVM(refp);

		numCount++;
		ret.push_back(son);
	}
	exist_vms.insert(exist_vms.end(),ret.begin(),ret.end());

	ret.pop_front();

	levelCount++;
	if(_maxLevel>0 && levelCount>=_maxLevel)
		return;

	for (itr2 = ret.begin(); itr2 != ret.end(); itr2++) {	
		p = (*itr2);
		d_expand(p,numCount,levelCount);
	}
	/*Basic_Dynamic_lyvm* lyvm = layoutLibrary::getInstance()->getCurrentEnabledDynamicLy();
	if(exist_vms.size() != 0 && lyvm != NULL){
		lyvm->layout(exist_vms);
	}*/
}

bool ExploreBot::checkExplorRef(string refName)
{
	auto itr = find(_selectRef.begin(),_selectRef.end(),refName);

	if(itr == _selectRef.end())
		return false;
	else
		return true;
}

string ExploreBot::getVarname()
{
	return _startVMname;
}

int ExploreBot::getLevel()
{
	return _maxLevel;
}

int ExploreBot::getNum()
{
	return _maxNum;
}

vector<string> ExploreBot::getRefs()
{
	return _selectRef;
}

string ExploreBot::getName()
{
	return _botName;
}


void ExploreBot::pickUpAllVMs(){
	//if(p->getVMType() != "reference") 
	vector<DIVA_VMStub*> vms = xVMRelationStructStub::getInstance()->VMRS_getAllVM();
	for(int i=0; i<vms.size();i++){
		if (vms.at(i)->getVMType() == "reference"){
			vms.at(i)->VMPicked(0,0,0);
		}
	}
}

void ExploreBot::setExAllref(bool i){
	_exallRef = i;
}

bool ExploreBot::getStats(){
	return _Success;
}

ExploreBotDialogStub* ExploreBot::getDialog(){
	if (_ui == NULL)
	{
		_ui = new ExploreBotDialogStub(0,0,NULL,this);
	}
	assert(_ui!=NULL);
	return _ui;
}

void ExploreBot::setDialog(ExploreBotDialogStub* ui){
	_ui = ui;
}

bool ExploreBot::saved(){
	return _save;
}

void ExploreBot::setSaved(bool i){
	_save = i;
}

bool ExploreBot::getTrigger(){
	return _isTrigger;
}

void ExploreBot::setTrigger(bool i){
	_isTrigger = i;
}

std::string ExploreBot::getMaxLevelString(){
	if (_maxLS == "")
	{ 
		std::stringstream ss;
		ss << _maxLevel;
		_maxLS = ss.str(); 
	}
	if(_maxLS == "500"){
		_maxLS = "(no limit)";
	}
	return _maxLS;
}

std::string ExploreBot::getMaxNumString(){
	if (_maxNS == "")
	{
		std::stringstream ss;
		ss << _maxNum;
		_maxNS = ss.str(); 
	}
	if(_maxNS == "500"){
		_maxNS = "(no limit)";
	}
	return _maxNS;
}

void ExploreBot::setMaxLevelString(std::string s){
	_maxLS = s;
}

void ExploreBot::setMaxNumString(std::string s){
	_maxNS = s;
}
std::vector<std::string> ExploreBot::getSelectRef(){
	return _selectRef;
}

std::string ExploreBot::getMessage(){
	return _message;
}
